package com.fjnldx.mes.service.scheduling.alarm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fjnldx.mes.domain.pojo.alarm.AlarmConfig;
import com.fjnldx.mes.domain.pojo.alarm.AlarmNotice;
import com.fjnldx.mes.domain.pojo.alarm.AlarmRecord;
import com.fjnldx.mes.domain.pojo.alarm.AlarmRules;
import com.fjnldx.mes.domain.pojo.alarm.enums.TriggerStatusEnum;
import com.fjnldx.mes.mapper.alarm.AlarmConfigMapper;
import com.fjnldx.mes.mapper.alarm.AlarmNoticeMapper;
import com.fjnldx.mes.mapper.alarm.AlarmRecordMapper;
import com.fjnldx.mes.mapper.alarm.AlarmRuleMapper;
import com.fjnldx.mes.service.scheduling.alarm.model.MonitorModel;
import com.fjnldx.mes.service.scheduling.alarm.notice.NoticeService;
import com.fjnldx.mes.service.scheduling.alarm.rule.inspector.AlarmRuleCheck;
import com.fjnldx.mes.service.scheduling.alarm.rule.relieve.AlarmRelieveCheck;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 告警调度器服务
 */
@Service
public class AlarmSchedulingService {

    @Resource
    private AlarmConfigMapper alarmConfigMapper;

    @Resource
    private AlarmRuleMapper alarmRuleMapper;

    @Resource
    private AlarmNoticeMapper alarmNoticeMapper;

    @Resource
    private AlarmRecordMapper alarmRecordMapper;

    private final List<AlarmRuleCheck> alarmRuleCheckList;
    private final List<NoticeService> noticeServiceList;
    private final List<AlarmRelieveCheck> relieveCheckList;

    private AlarmSchedulingService(List<AlarmRuleCheck> alarmRuleChecks, List<NoticeService> noticeServices, List<AlarmRelieveCheck> relieveChecks) {
        alarmRuleCheckList = alarmRuleChecks;
        noticeServiceList = noticeServices;
        relieveCheckList = relieveChecks;
    }

    /**
     * 获取所有告警配置
     *
     * @return 告警配置列表
     */
    public List<AlarmConfig> GetConfigs() throws Exception {
        try {
            QueryWrapper<AlarmConfig> configQueryWrapper = new QueryWrapper<>();
            configQueryWrapper.eq("isActive", true);
            return alarmConfigMapper.selectList(configQueryWrapper);
        } catch (Exception e) {
            throw new Exception();
        }
    }

    /**
     * 获取配置规则
     *
     * @param configIds 配置标识
     * @return 配置规则
     * @throws Exception 未知异常信息
     */
    public List<AlarmRules> GetConfigRules(List<Integer> configIds) throws Exception {
        try {
            //查询配置规则
            QueryWrapper<AlarmRules> alarmRulesQueryWrapper = new QueryWrapper<>();
            alarmRulesQueryWrapper.in("alarmId", configIds);
            return alarmRuleMapper.selectList(alarmRulesQueryWrapper);
        } catch (Exception e) {
            throw new Exception();
        }
    }

    /**
     * 获取告警通知配置
     *
     * @param configIds 告警配置标识
     * @return 通知配置
     * @throws Exception 未知异常
     */
    public List<AlarmNotice> GetConfigNotices(List<Integer> configIds) throws Exception {
        try {
            //查询配置规则
            QueryWrapper<AlarmNotice> alarmConfigQueryWrapper = new QueryWrapper<>();
            alarmConfigQueryWrapper.in("alarmId", configIds);
            return alarmNoticeMapper.selectList(alarmConfigQueryWrapper);
        } catch (Exception e) {
            throw new Exception();
        }
    }

    /**
     * 检查规则是否被触发
     *
     * @param rule 规则信息
     * @return 响应是否被触发
     */
    public MonitorModel CheckRule(AlarmRules rule) {
        List<AlarmRuleCheck> itemCheckServices = alarmRuleCheckList.stream().filter(service -> service.monitoringType() == rule.getMonitorType()).collect(Collectors.toList());
        for (AlarmRuleCheck checkService : itemCheckServices) {
            MonitorModel result = checkService.Check(rule);
            if (null != result && result.getWhetherTrigger()) return result;
        }
        return null;
    }

    /**
     * 触发通知
     *
     * @param config 通知设置
     */
    public void TriggerNotice(AlarmConfig config, AlarmRules rule, List<AlarmNotice> notice, MonitorModel monitor) {
        QueryWrapper<AlarmRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("alarmId", config.getId());
        queryWrapper.eq("status", TriggerStatusEnum.ABNORMAL);
        int recorded = alarmRecordMapper.selectCount(queryWrapper);
        if (recorded > 0) return;
        //发送通知
        for (AlarmNotice noticeItem : notice) {
            String content = noticeItem.getMessageTemplate();
            content = content.replace("{EventName}", config.getName());
            content = content.replace("{DataSource}", monitor.getDevSn() != null ? monitor.getDevSn() : "");
            content = content.replace("{WarnName}", rule.getName());
            content = content.replace("{WarnCode}", rule.getId().toString());
            content = content.replace("{ValueName}", monitor.getCsName());
            content = content.replace("{CollectionValue}", monitor.getCollect());
            content = content.replace("{Time}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            //记录通知
            AlarmRecord record = new AlarmRecord();
            record.setAlarmId(config.getId());
            record.setAlarmName(config.getName());
            record.setDicBh(monitor.getDicBh());
            record.setDevSn(monitor.getDevSn());
            record.setCs(monitor.getCs());
            record.setCsName(monitor.getCsName());
            record.setStandard(monitor.getStandard());
            record.setCollect(monitor.getCollect());
            record.setOperator(monitor.getOperator());
            record.setRuleName(rule.getName());
            record.setLevel(rule.getLevel());
            record.setNote(content);
            record.setStatus(TriggerStatusEnum.ABNORMAL);
            record.setCreateTime(LocalDateTime.now());
            alarmRecordMapper.insert(record);
        }
    }

    public List<AlarmRecord> GetAlarmRecord() throws Exception {
        try {
            QueryWrapper<AlarmRecord> recordQueryWrapper = new QueryWrapper<>();
            recordQueryWrapper.eq("status", TriggerStatusEnum.ABNORMAL);
            return alarmRecordMapper.selectList(recordQueryWrapper);
        } catch (Exception e) {
            throw new Exception();
        }
    }

    /**
     * 检查告警是否被解除
     *
     * @param rule 规则信息
     * @return 响应是否被触发
     * @throws Exception 未知异常信息
     */
    public Boolean CheckRelieve(AlarmRules rule, AlarmRecord record) throws Exception {
        try {
            List<AlarmRelieveCheck> relieveChecks = relieveCheckList.stream().filter(service -> service.RelieveType() == rule.getRelieveType()).collect(Collectors.toList());
            return relieveChecks.stream().anyMatch(service -> {
                try {
                    return service.Check(rule, record);
                } catch (Exception e) {
                    return false;
                }
            });

        } catch (Exception e) {
            throw new Exception();
        }
    }

    /**
     * 解除告警
     *
     * @throws Exception 未知异常信息
     */
    public void RelieveAlarm(AlarmRecord record) throws Exception {
        try {
            record.setStatus(TriggerStatusEnum.NORMAL);
            alarmRecordMapper.updateById(record);
        } catch (Exception e) {
            throw new Exception();
        }
    }
}
